feat: expose response headers via thread-safe contextvars#764
feat: expose response headers via thread-safe contextvars#764brianfeucht wants to merge 1 commit intoauth0:masterfrom
Conversation
Implement a thread-safe and async-safe way to access response headers using Python's contextvars module.
Changes:
- Add ContextVar to store response headers isolated per execution context (thread/async task)
- Add last_response_headers property to RestClient for accessing rate-limit and other response metadata
- Update EmptyResponse to preserve headers from 204 responses
- Comprehensive tests covering thread isolation, successive requests, and various HTTP methods
Benefits:
- Zero breaking changes - fully backwards compatible
- Minimal code footprint - only rest.py modified
- Thread-safe and async-safe via contextvars (Python 3.7+)
- No per-class boilerplate (eliminates need for 32 duplicate properties)
Usage:
users = Users(domain="tenant.auth0.com", token="token")
users.create({"email": "user@example.com"})
headers = users.client.last_response_headers
remaining = int(headers.get("X-RateLimit-Remaining", 0))
6de0387 to
4b7c793
Compare
|
Thanks @brianfeucht for submitting. As a long-time consumer of this SDK, not having the ability to perform graceful backoff before hitting rate limits has been a huge drawback in comparison to other official Auth0 SDKs that do support returning active rate limit usage. |
|
Hi @brianfeucht, Thank you so much for this excellent contribution! 🙏 We really appreciate the time and effort you put into implementing thread-safe response header access, and the comprehensive test coverage you provided is outstanding. However, I wanted to let you know that we're currently releasing v5.0.0 of the Auth0 Python SDK, which includes a complete rewrite of the Management API client using Fern code generation. The good news is that response header access is already built into v5 through Fern's standard How it works in v5:from auth0.management import ManagementClient
client = ManagementClient(
domain='your-tenant.auth0.com',
client_id='your_client_id',
client_secret='your_client_secret'
)
# Access response headers using with_raw_response
response = client.clients.with_raw_response.get(id='client_id')
# Headers are available on the response object
headers = response.headers
print(f"Rate limit: {headers['x-ratelimit-limit']}")
print(f"Remaining: {headers['x-ratelimit-remaining']}")
print(f"Reset: {headers['x-ratelimit-reset']}")
# Access the data
data = response.data Given this, we'll be closing this PR as the functionality is now available in a more comprehensive way through v5. Once v5.0.0 is officially released (coming very soon!), I'll update his comment with a link to the release notes and migration guide. Your work highlighted an important gap in v4, and we're glad that v5 addresses this need out of the box. Thanks again for your valuable contribution to the Auth0 Python SDK community! 🙌 Update: v5.0.0 has been released! Check out the https://github.com/auth0/auth0-python/releases/tag/5.0.0 and https://github.com/auth0/auth0-python/blob/master/v5_MIGRATION_GUIDE.md for more details. |
This PR introduces a thread-safe and async-safe way to access HTTP response headers (especially rate-limit information) from Auth0's Management API responses.
Changes
Added
ContextVarfor thread-safe header storage (auth0/rest.py)Added
last_response_headersproperty toRestClientRestClientclassdict[str, str]containing rate-limit and other response headersUpdated
EmptyResponseto preserve headers from 204 responsesTest suite (
auth0/test/test_rest_headers_contextvar.py)References
Testing
This PR includes comprehensive testing:
Unit Tests Added: 8 Tests (All Passing ✅)
test_headers_accessible_after_request- Verifies headers are stored and accessible after successful API callstest_headers_on_204_response- Confirms headers are preserved on 204 No Content responsestest_headers_updated_on_successive_requests- Validates headers are updated with each new requesttest_headers_empty_initially- Confirms empty dict before any API callstest_thread_isolation- KEY TEST: Verifies each thread sees its own headers (not contaminated by other threads)test_headers_in_same_context_reflect_latest_request- Confirms context-specific behaviortest_post_request_headers- Headers work on POST requeststest_patch_request_headers- Headers work on PATCH requestsTest Coverage
Existing Tests
Checklist